Skip to content

Conversation

@weizhouapache
Copy link
Member

Description

This PR fixes #12186

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?

How did you try to break this feature and the system with this change?

@weizhouapache
Copy link
Member Author

@blueorangutan package

@blueorangutan
Copy link

@weizhouapache a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

@codecov
Copy link

codecov bot commented Jan 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 4.03%. Comparing base (cd5bb09) to head (976b969).
⚠️ Report is 4 commits behind head on 4.20.

❗ There is a different number of reports uploaded between BASE (cd5bb09) and HEAD (976b969). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (cd5bb09) HEAD (976b969)
unittests 1 0
Additional details and impacted files
@@              Coverage Diff              @@
##               4.20   #12499       +/-   ##
=============================================
- Coverage     17.10%    4.03%   -13.08%     
=============================================
  Files          5255      402     -4853     
  Lines        466415    32721   -433694     
  Branches      54746     5832    -48914     
=============================================
- Hits          79763     1319    -78444     
+ Misses       377768    31247   -346521     
+ Partials       8884      155     -8729     
Flag Coverage Δ
uitests 4.03% <ø> (?)
unittests ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@DaanHoogland DaanHoogland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clgtm, one (dumb luser) question .

Comment on lines 128 to 130
if (registerCmd.isDeployAsIs() && CollectionUtils.isNotEmpty(registerCmd.getVnfNics())) {
throw new InvalidParameterValueException("VNF Template cannot be registered with VNF nics as Template settings are read from OVA.");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want this always to be true? I could imagine a VNF getting a default gateway… Probably my lack of knowledge. I hope this is in the documentation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (registerCmd.isDeployAsIs() && CollectionUtils.isNotEmpty(registerCmd.getVnfNics())) {
throw new InvalidParameterValueException("VNF Template cannot be registered with VNF nics as Template settings are read from OVA.");
}
if (registerCmd.isDeployAsIs() && CollectionUtils.isNotEmpty(registerCmd.getVnfNics())) {
throw new InvalidParameterValueException("VNF nics cannot be specified when register a deploy-as-is Template. Please wait until Template settings are read from OVA.");
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it clear now ? @DaanHoogland

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for deploying VNF appliances using deploy-as-is templates (OVA files) by allowing the VNF template functionality to work with templates that have network configurations already defined in the OVA. Previously, deploying such templates failed with "VNF nics list is empty" error.

Changes:

  • Added conditional validation logic to handle both regular VNF templates (using networkIds list) and deploy-as-is VNF templates (using vmNetworkMap)
  • Modified UI to disable network selection when deploy-as-is template networks are pre-configured
  • Added validation to prevent registering/updating VNF nics on deploy-as-is templates since settings are read from the OVA

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
ui/src/views/compute/wizard/VnfNicsSelection.vue Adds templateNics prop and disables network selection for deploy-as-is templates
ui/src/views/compute/DeployVnfAppliance.vue Passes templateNics to VnfNicsSelection component and updates validation logic to handle deploy-as-is template networks
api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManager.java Adds new interface method validateVnfApplianceNetworksMap for deploy-as-is template validation
server/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateManagerImpl.java Implements validateVnfApplianceNetworksMap and adds check to prevent VNF nics on deploy-as-is templates
api/src/main/java/org/apache/cloudstack/storage/template/VnfTemplateUtils.java Adds validation methods for deploy-as-is templates: prevents VNF nics registration and validates OVF networks
server/src/main/java/com/cloud/vm/UserVmManagerImpl.java Routes to appropriate validation method based on whether template is deploy-as-is
server/src/main/java/com/cloud/template/TemplateManagerImpl.java Adds validation for VNF nics updates on deploy-as-is templates using OVF network data
server/src/test/java/com/cloud/template/TemplateManagerImplTest.java Adds mock bean for TemplateDeployAsIsDetailsDao to support new validation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +165 to +167
if (vnfNic.getDeviceId() < ovfNetworks.size() && !vnfNic.isRequired()) {
throw new InvalidParameterValueException(String.format("The VNF nic [device ID: %s ] is required as it is defined in the OVA template.", vnfNic.getDeviceId()));
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation logic has a flaw. It checks if vnfNic.getDeviceId() < ovfNetworks.size() && !vnfNic.isRequired(), which throws an error if the vnfNic is NOT required. This is backwards - the error message says "The VNF nic [device ID: %s ] is required" but the condition checks !vnfNic.isRequired(). The logic should be: if the device ID corresponds to an OVF network, the VNF nic MUST be required. So the condition should be checking if it's defined in OVF but marked as not required in the VNF configuration.

Copilot uses AI. Check for mistakes.
Comment on lines 219 to 230
@Override
public void validateVnfApplianceNetworksMap(VirtualMachineTemplate template, Map<Integer, Long> vmNetworkMap) {
if (MapUtils.isEmpty(vmNetworkMap)) {
throw new InvalidParameterValueException("VNF networks map is empty");
}
List<VnfTemplateNicVO> vnfNics = vnfTemplateNicDao.listByTemplateId(template.getId());
for (VnfTemplateNicVO vnfNic : vnfNics) {
if (vnfNic.isRequired() && vmNetworkMap.size() <= vnfNic.getDeviceId()) {
throw new InvalidParameterValueException("VNF nic is required but not found: " + vnfNic);
}
}
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new method validateVnfApplianceNetworksMap is not covered by any unit tests. Since this is a critical validation method for deploy-as-is VNF templates and similar validation methods in the codebase have test coverage, unit tests should be added to verify the validation logic works correctly.

Copilot uses AI. Check for mistakes.
Comment on lines +157 to +169
public static void validateDeployAsIsTemplateVnfNics(List<OVFNetworkTO> ovfNetworks, List<VNF.VnfNic> vnfNics) {
if (CollectionUtils.isEmpty(vnfNics)) {
return;
}
if (CollectionUtils.isEmpty(ovfNetworks)) {
throw new InvalidParameterValueException("The list of networks read from OVA is empty. Please wait until the template is fully downloaded and processed.");
}
for (VNF.VnfNic vnfNic : vnfNics) {
if (vnfNic.getDeviceId() < ovfNetworks.size() && !vnfNic.isRequired()) {
throw new InvalidParameterValueException(String.format("The VNF nic [device ID: %s ] is required as it is defined in the OVA template.", vnfNic.getDeviceId()));
}
}
}
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new method validateDeployAsIsTemplateVnfNics is not covered by any unit tests. This is a new validation method for deploy-as-is VNF templates, and given that similar validation methods in the codebase have test coverage, unit tests should be added to ensure the validation logic works as expected.

Copilot uses AI. Check for mistakes.
@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 16480

if (cmd instanceof UpdateVnfTemplateCmd) {
VnfTemplateUtils.validateApiCommandParams(cmd, template);
UpdateVnfTemplateCmd updateCmd = (UpdateVnfTemplateCmd) cmd;
if (template.isDeployAsIs() && CollectionUtils.isNotEmpty(updateCmd.getVnfNics())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nvazquez
when register a deploy-as-is template, the template NICs are not available until the template is downloaded successfully.
I think it is better that user configures VNF nics only when template NICs are fetched from OVA template.

@github-actions
Copy link

This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch.

@RosiKyu RosiKyu self-assigned this Jan 22, 2026
@RosiKyu
Copy link
Collaborator

RosiKyu commented Jan 22, 2026

NOTE #12436 (comment) -> check tooltip fix while verifying this PR

@weizhouapache
Copy link
Member Author

@blueorangutan package

@weizhouapache
Copy link
Member Author

thanks @DaanHoogland

@nvazquez can you please review ? thanks

Copy link
Collaborator

@RosiKyu RosiKyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Tests Execution Summary

TC Description Status
TC1 Deploy VNF via API PASSED
TC2 Deploy VNF via UI PASSED
TC3 Register deploy-as-is without VNF NICs PASSED
TC4 Register deploy-as-is with VNF NICs (negative) PASSED
TC5 Update deploy-as-is template with VNF NICs PASSED
TC6 UI network selection behavior PASSED
TC7 Deploy with all NICs mapped correctly PASSED
TC8 Deploy with missing NIC mapping PASSED
TC9 Verify VNF functionality post-deploy PASSED
TC10 Multiple deployments from same template PASSED
TC11 Regression – regular VNF template PASSED

Result: 11/11 test cases PASSED.

Environment

CloudStack: 4.20.3.0-SNAPSHOT (PR #12499)
Hypervisor: VMware
Template: Cisco ASAv OVA (10 NICs)

Key Findings

  • Main bug fixed: Deploy-as-is VNF templates now deploy successfully via nicnetworklist parameter
  • NIC mapping: nicnetworklist[X].nic must use OVA InstanceID values (e.g., 6, 9, 10...), not sequential device IDs
  • Auto-fill behavior: Unspecified NICs are auto-filled with zone's default network (intentional design)
  • No regression: Regular VNF templates still work with networkids parameter

Separate Issue Found

Bug #12510: This is a separate UI bug, not related to PR #12499
**Workaround: ** Deploy via CloudMonkey CLI with properties[0].key=HARole properties[0].value=Standalone

Detailed Test Results

TC1: Deploy VNF Appliance via Deploy-as-is Template (Main Bug Fix)

Objective: Verify the original bug is fixed - deploying VNF appliance using deploy-as-is template no longer fails with "VNF nics list is empty"
Expected Result: VM deploys successfully without "VNF nics list is empty" error
Actual Result: PASSED - VM ID: 4d319d1f-8de8-4b05-84ba-8b580d731ca5, State: Running, 10 NICs created
Test Evidence:

(localcloud) 🐱 > deployVnfAppliance templateid=88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd serviceofferingid=63b6851c-631c-4b30-81f0-e959e2eb6052 zoneid=e9594751-da68-4f49-924f-222ba4c15876 nicnetworklist[0].nic=0 nicnetworklist[0].network=4935f651-04b5-49f7-b25a-55c6151ad5cb name=vnf-tc1-full properties[0].key=HARole properties[0].value=Standalone
{
  "virtualmachine": {
    "account": "admin",
    "affinitygroup": [],
    "arch": "x86_64",
    "cpunumber": 1,
    "cpuspeed": 500,
    "created": "2026-01-23T08:22:14+0000",
    "deleteprotection": false,
    "details": {
      "cpuOvercommitRatio": "2.0",
      "dataDiskController": "osdefault",
      "rootDiskController": "lsilogic"
    },
    "displayname": "vnf-tc1-full",
    "displayvm": true,
    "domain": "ROOT",
    "domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
    "domainpath": "/",
    "guestosid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
    "haenable": false,
    "hasannotations": false,
    "hostcontrolstate": "Enabled",
    "hostid": "cfcf5c46-b2dc-4c40-b487-eb8a111a83b3",
    "hostname": "10.0.35.172",
    "hypervisor": "VMware",
    "id": "4d319d1f-8de8-4b05-84ba-8b580d731ca5",
    "instancename": "i-2-7-VM",
    "ipaddress": "10.1.1.52",
    "isdynamicallyscalable": false,
    "jobid": "4db54012-7faa-4eb0-833f-8eac824d7b27",
    "jobstatus": 0,
    "lastupdated": "2026-01-23T08:24:11+0000",
    "memory": 512,
    "name": "vnf-tc1-full",
    "nic": [
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "2",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "a46379db-2c9b-4656-bfb5-bfd99adb366a",
        "ipaddress": "10.1.1.114",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:18",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "8",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "f7e2761b-73f0-4f67-99ba-fc663695d863",
        "ipaddress": "10.1.1.185",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:1e",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "4",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "9e609129-55c8-4ed5-bb84-35a27fc39deb",
        "ipaddress": "10.1.1.197",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:1a",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "9",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "ccc16eb3-9e07-47f5-9dc2-faed9afd7eb6",
        "ipaddress": "10.1.1.137",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:1f",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "7",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "0afd124b-8c07-4db5-bdc0-b2858043ceea",
        "ipaddress": "10.1.1.38",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:1d",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "3",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "9176d2c0-a91e-4c3e-8ca1-207a3b792475",
        "ipaddress": "10.1.1.240",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:19",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "6",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "fbf965f5-ec8e-4806-a514-7f3b520a2b66",
        "ipaddress": "10.1.1.150",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:1c",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "0",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "ca0d01fe-4696-472b-8923-2961ee65edc3",
        "ipaddress": "10.1.1.52",
        "isdefault": true,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:16",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "1",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "9017b11f-b315-4812-82bb-b8b1a3d3a682",
        "ipaddress": "10.1.1.202",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:17",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "5",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "e9f8916a-ba2d-4d95-a667-dce690ace4aa",
        "ipaddress": "10.1.1.81",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:1b",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      }
    ],
    "osdisplayname": "Other 2.6x Linux (64-bit)",
    "ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
    "passwordenabled": false,
    "pooltype": "PreSetup",
    "receivedbytes": 0,
    "rootdeviceid": 0,
    "rootdevicetype": "ROOT",
    "securitygroup": [],
    "sentbytes": 0,
    "serviceofferingid": "63b6851c-631c-4b30-81f0-e959e2eb6052",
    "serviceofferingname": "Small Instance",
    "state": "Running",
    "tags": [],
    "templatedisplaytext": "ASAv VNF deploy-as-is test",
    "templateformat": "OVA",
    "templateid": "88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd",
    "templatename": "ASAv-VNF-test-vnf",
    "templatetype": "VNF",
    "userid": "1095c455-f7cd-11f0-bc70-1e00b6000327",
    "username": "admin",
    "zoneid": "e9594751-da68-4f49-924f-222ba4c15876",
    "zonename": "ref-trl-10698-v-Mol8-rositsa-kyuchukova"
  }
}

TC2 (UI): Deploy VNF Appliance via UI with Deploy-as-is Template

Objective: Verify the original bug is fixed via UI - Deploy VNF Appliance wizard works with deploy-as-is templates
Expected Result: VM deploys successfully via UI without "VNF nics list is empty" error
Actual Result: PASSED - VM created with 10 NICs properly mapped to networks
Test Evidence:

  • Deploying via UI
Screencast.from.2026-01-23.10-43-23.webm
Screenshot from 2026-01-23 10-44-02
  • Launching VNF appliance
image

NOTE Identified a separate UI bug, while executing this test case: #12510

TC3: Register Deploy-as-is VNF Template WITHOUT VNF Nics

Objective: Verify registering a deploy-as-is VNF template without specifying VNF nics succeeds
Expected Result: Template registers successfully; VNF nics read from OVA after download
Actual Result: PASSED - Template ID: 3dc7c5e0-46ad-4531-a8e4-149461be237f, Status: Ready, 10 NICs auto-populated from OVA
Test Evidence:

(localcloud) 🐱 > listVnfTemplates id=3dc7c5e0-46ad-4531-a8e4-149461be237f templatefilter=all filter=id,name,status,isready,templatetype,deployasis
{
  "count": 1,
  "template": [
    {
      "deployasis": true,
      "id": "3dc7c5e0-46ad-4531-a8e4-149461be237f",
      "isready": true,
      "name": "vnf-tc3-no-nics",
      "status": "Download Complete",
      "templatetype": "VNF"
    }
  ]
}
(localcloud) 🐱 >  
image

TC4: Register Deploy-as-is VNF Template WITH VNF Nics (Negative Test)

Objective: Verify proper error when trying to register deploy-as-is template with VNF nics specified
Expected Result: Error rejecting VNF nics parameter for deploy-as-is templates
Actual Result: PASSED - Proper validation error returned
Test Evidence:

(localcloud) 🐱 > registerVnfTemplate name=vnf-tc4-with-nics displaytext="TC4 VNF with nics - should fail" format=OVA hypervisor=VMware ostypeid=cac8e8aa-f7cc-11f0-bc70-1e00b6000327 zoneid=e9594751-da68-4f49-924f-222ba4c15876 url=http://10.0.3.122/ova/asav951.ova deployasis=true vnfnics[0].deviceid=0 vnfnics[0].name=eth0 vnfnics[0].required=true
🙈 Error: (HTTP 431, error code 4350) VNF Template cannot be registered with VNF nics as Template settings are read from OVA.

TC5: Update Deploy-as-is VNF Template with VNF Nics

Objective: Verify updating deploy-as-is template to add VNF nics is allowed after template is ready
Expected Result: Update succeeds - user can configure VNF nics after OVA is downloaded
Actual Result: PASSED - VNF nics were added successfully
Test Evidence:

(localcloud) 🐱 > updateVnfTemplate id=3dc7c5e0-46ad-4531-a8e4-149461be237f vnfnics[0].deviceid=0 vnfnics[0].name=eth0 vnfnics[0].required=true
{
  "template": {
    "account": "admin",
    "bits": 0,
    "bootable": true,
    "created": "2026-01-23T09:21:09+0000",
    "crossZones": false,
    "displaytext": "TC3 VNF without nics",
    "domain": "ROOT",
    "domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
    "domainpath": "/",
    "format": "OVA",
    "hypervisor": "VMware",
    "id": "3dc7c5e0-46ad-4531-a8e4-149461be237f",
    "isdynamicallyscalable": false,
    "isfeatured": false,
    "ispublic": false,
    "isready": false,
    "name": "vnf-tc3-no-nics",
    "ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
    "ostypename": "Other 2.6x Linux (64-bit)",
    "tags": [],
    "templatetype": "VNF",
    "vnfnics": [
      {
        "deviceid": 0,
        "management": true,
        "name": "eth0",
        "required": true
      }
    ]
  }
}

TC6: UI - Network Selection Behavior for Deploy-as-is Template

Objective: Verify UI properly handles network selection for deploy-as-is templates
Expected Result: UI displays all OVA-defined NICs with functional network selection; no option to modify NIC definitions
Actual Result: PASSED - All 10 NICs from OVA displayed with correct names, "Change" button functional, no add/remove options
Evidence

image image image image

TC7: Deploy VNF with All Required NICs Mapped

Objective: Verify deployment succeeds when all required NICs have networks assigned

Expected Result: Deployment succeeds; VM has correct network attachments matching the specified mapping

Actual Result: PARTIAL PASS / POTENTIAL BUG - VM deployed successfully with 10 NICs in Running state, but network mapping does not match the specified nicnetworklist parameter. Only 3/10 NICs attached to correct networks.

Test Evidence:

(localcloud) 🐱 > deployVnfAppliance templateid=88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd serviceofferingid=63b6851c-631c-4b30-81f0-e959e2eb6052 zoneid=e9594751-da68-4f49-924f-222ba4c15876 name=vnf-tc7-correct-ids properties[0].key=HARole properties[0].value=Standalone nicnetworklist[0].nic=6 nicnetworklist[0].network=4935f651-04b5-49f7-b25a-55c6151ad5cb nicnetworklist[1].nic=9 nicnetworklist[1].network=fee6a3ae-b99f-4ebe-b84b-c661fc4d5888 nicnetworklist[2].nic=10 nicnetworklist[2].network=a170136d-9699-4586-8eaf-f83f19255a54 nicnetworklist[3].nic=11 nicnetworklist[3].network=9427bebb-848d-4b54-8e22-06bfdcc83dcd nicnetworklist[4].nic=12 nicnetworklist[4].network=4935f651-04b5-49f7-b25a-55c6151ad5cb nicnetworklist[5].nic=13 nicnetworklist[5].network=fee6a3ae-b99f-4ebe-b84b-c661fc4d5888 nicnetworklist[6].nic=14 nicnetworklist[6].network=a170136d-9699-4586-8eaf-f83f19255a54 nicnetworklist[7].nic=15 nicnetworklist[7].network=9427bebb-848d-4b54-8e22-06bfdcc83dcd nicnetworklist[8].nic=16 nicnetworklist[8].network=4935f651-04b5-49f7-b25a-55c6151ad5cb nicnetworklist[9].nic=17 nicnetworklist[9].network=fee6a3ae-b99f-4ebe-b84b-c661fc4d5888
{
  "virtualmachine": {
    "account": "admin",
    "affinitygroup": [],
    "arch": "x86_64",
    "cpunumber": 1,
    "cpuspeed": 500,
    "created": "2026-01-23T10:26:18+0000",
    "deleteprotection": false,
    "details": {
      "cpuOvercommitRatio": "2.0",
      "dataDiskController": "osdefault",
      "rootDiskController": "lsilogic"
    },
    "displayname": "vnf-tc7-correct-ids",
    "displayvm": true,
    "domain": "ROOT",
    "domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
    "domainpath": "/",
    "guestosid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
    "haenable": false,
    "hasannotations": false,
    "hostcontrolstate": "Enabled",
    "hostid": "7a9c02a7-19f8-46a1-9ef3-a4ff7fe90ba6",
    "hostname": "10.0.35.255",
    "hypervisor": "VMware",
    "id": "3093cba4-9238-44f7-a5d4-198e4df0cad6",
    "instancename": "i-2-15-VM",
    "ipaddress": "10.1.1.65",
    "isdynamicallyscalable": false,
    "jobid": "1cb3ca2e-9052-4e73-bf79-f0a569261530",
    "jobstatus": 0,
    "lastupdated": "2026-01-23T10:29:53+0000",
    "memory": 512,
    "name": "vnf-tc7-correct-ids",
    "nic": [
      {
        "broadcasturi": "vlan://1175",
        "deviceid": "5",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "54fd720d-aed4-47fa-aef3-2ec59541f9a9",
        "ipaddress": "10.1.1.27",
        "isdefault": false,
        "isolationuri": "vlan://1175",
        "macaddress": "02:01:00:ce:00:07",
        "netmask": "255.255.255.0",
        "networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
        "networkname": "vnf-net2",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1175",
        "deviceid": "9",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "c3473e84-b1d3-4de3-93c2-5144dc48e683",
        "ipaddress": "10.1.1.32",
        "isdefault": false,
        "isolationuri": "vlan://1175",
        "macaddress": "02:01:00:ce:00:08",
        "netmask": "255.255.255.0",
        "networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
        "networkname": "vnf-net2",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1179",
        "deviceid": "8",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "9181e5aa-7b27-47fc-9095-4eca7a4138c7",
        "ipaddress": "10.1.1.201",
        "isdefault": false,
        "isolationuri": "vlan://1179",
        "macaddress": "02:01:00:cd:00:07",
        "netmask": "255.255.255.0",
        "networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
        "networkname": "vnf-net1",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1164",
        "deviceid": "2",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "e6be4593-cc05-422d-a768-2702bdf64806",
        "ipaddress": "10.1.1.98",
        "isdefault": false,
        "isolationuri": "vlan://1164",
        "macaddress": "02:01:00:cf:00:06",
        "netmask": "255.255.255.0",
        "networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
        "networkname": "vnf-net3",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1179",
        "deviceid": "0",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "eb098621-fbe9-4914-a74e-656fbcc3eff9",
        "ipaddress": "10.1.1.65",
        "isdefault": true,
        "isolationuri": "vlan://1179",
        "macaddress": "02:01:00:cd:00:05",
        "netmask": "255.255.255.0",
        "networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
        "networkname": "vnf-net1",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1164",
        "deviceid": "6",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "3ae4f2e9-9b87-4b81-b988-1dfff6b62765",
        "ipaddress": "10.1.1.72",
        "isdefault": false,
        "isolationuri": "vlan://1164",
        "macaddress": "02:01:00:cf:00:07",
        "netmask": "255.255.255.0",
        "networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
        "networkname": "vnf-net3",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1179",
        "deviceid": "4",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "3a78494a-d496-4cd7-a899-610d85a917d5",
        "ipaddress": "10.1.1.27",
        "isdefault": false,
        "isolationuri": "vlan://1179",
        "macaddress": "02:01:00:cd:00:06",
        "netmask": "255.255.255.0",
        "networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
        "networkname": "vnf-net1",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "7",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "3e6a983f-5e01-4859-93ac-0c57a6d8e7dc",
        "ipaddress": "10.1.1.160",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:3e",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1175",
        "deviceid": "1",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "34a285a4-f3f4-4314-80aa-376a194b8abf",
        "ipaddress": "10.1.1.162",
        "isdefault": false,
        "isolationuri": "vlan://1175",
        "macaddress": "02:01:00:ce:00:06",
        "netmask": "255.255.255.0",
        "networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
        "networkname": "vnf-net2",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "3",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "9236a428-b995-4866-918a-0257ada77b09",
        "ipaddress": "10.1.1.229",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:3d",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      }
    ],
    "osdisplayname": "Other 2.6x Linux (64-bit)",
    "ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
    "passwordenabled": false,
    "pooltype": "PreSetup",
    "receivedbytes": 0,
    "rootdeviceid": 0,
    "rootdevicetype": "ROOT",
    "securitygroup": [],
    "sentbytes": 0,
    "serviceofferingid": "63b6851c-631c-4b30-81f0-e959e2eb6052",
    "serviceofferingname": "Small Instance",
    "state": "Running",
    "tags": [],
    "templatedisplaytext": "ASAv VNF deploy-as-is test",
    "templateformat": "OVA",
    "templateid": "88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd",
    "templatename": "ASAv-VNF-test-vnf",
    "templatetype": "VNF",
    "userid": "1095c455-f7cd-11f0-bc70-1e00b6000327",
    "username": "admin",
    "zoneid": "e9594751-da68-4f49-924f-222ba4c15876",
    "zonename": "ref-trl-10698-v-Mol8-rositsa-kyuchukova"
  }
}
  • VNF Appliance deployed, in a Running state
(localcloud) 🐱 > listVirtualMachines name=vnf-tc7-correct-ids filter=id,name,state,nic
{
  "count": 1,
  "virtualmachine": [
    {
      "id": "3093cba4-9238-44f7-a5d4-198e4df0cad6",
      "name": "vnf-tc7-correct-ids",
      "nic": [
        {
          "broadcasturi": "vlan://1179",
          "deviceid": "0",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "eb098621-fbe9-4914-a74e-656fbcc3eff9",
          "ipaddress": "10.1.1.65",
          "isdefault": true,
          "isolationuri": "vlan://1179",
          "macaddress": "02:01:00:cd:00:05",
          "netmask": "255.255.255.0",
          "networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
          "networkname": "vnf-net1",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        },
        {
          "broadcasturi": "vlan://1175",
          "deviceid": "1",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "34a285a4-f3f4-4314-80aa-376a194b8abf",
          "ipaddress": "10.1.1.162",
          "isdefault": false,
          "isolationuri": "vlan://1175",
          "macaddress": "02:01:00:ce:00:06",
          "netmask": "255.255.255.0",
          "networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
          "networkname": "vnf-net2",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        },
        {
          "broadcasturi": "vlan://1164",
          "deviceid": "2",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "e6be4593-cc05-422d-a768-2702bdf64806",
          "ipaddress": "10.1.1.98",
          "isdefault": false,
          "isolationuri": "vlan://1164",
          "macaddress": "02:01:00:cf:00:06",
          "netmask": "255.255.255.0",
          "networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
          "networkname": "vnf-net3",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        },
        {
          "broadcasturi": "vlan://1161",
          "deviceid": "3",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "9236a428-b995-4866-918a-0257ada77b09",
          "ipaddress": "10.1.1.229",
          "isdefault": false,
          "isolationuri": "vlan://1161",
          "macaddress": "02:01:00:cc:00:3d",
          "netmask": "255.255.255.0",
          "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
          "networkname": "test",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        },
        {
          "broadcasturi": "vlan://1179",
          "deviceid": "4",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "3a78494a-d496-4cd7-a899-610d85a917d5",
          "ipaddress": "10.1.1.27",
          "isdefault": false,
          "isolationuri": "vlan://1179",
          "macaddress": "02:01:00:cd:00:06",
          "netmask": "255.255.255.0",
          "networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
          "networkname": "vnf-net1",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        },
        {
          "broadcasturi": "vlan://1175",
          "deviceid": "5",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "54fd720d-aed4-47fa-aef3-2ec59541f9a9",
          "ipaddress": "10.1.1.27",
          "isdefault": false,
          "isolationuri": "vlan://1175",
          "macaddress": "02:01:00:ce:00:07",
          "netmask": "255.255.255.0",
          "networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
          "networkname": "vnf-net2",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        },
        {
          "broadcasturi": "vlan://1164",
          "deviceid": "6",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "3ae4f2e9-9b87-4b81-b988-1dfff6b62765",
          "ipaddress": "10.1.1.72",
          "isdefault": false,
          "isolationuri": "vlan://1164",
          "macaddress": "02:01:00:cf:00:07",
          "netmask": "255.255.255.0",
          "networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
          "networkname": "vnf-net3",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        },
        {
          "broadcasturi": "vlan://1161",
          "deviceid": "7",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "3e6a983f-5e01-4859-93ac-0c57a6d8e7dc",
          "ipaddress": "10.1.1.160",
          "isdefault": false,
          "isolationuri": "vlan://1161",
          "macaddress": "02:01:00:cc:00:3e",
          "netmask": "255.255.255.0",
          "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
          "networkname": "test",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        },
        {
          "broadcasturi": "vlan://1179",
          "deviceid": "8",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "9181e5aa-7b27-47fc-9095-4eca7a4138c7",
          "ipaddress": "10.1.1.201",
          "isdefault": false,
          "isolationuri": "vlan://1179",
          "macaddress": "02:01:00:cd:00:07",
          "netmask": "255.255.255.0",
          "networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
          "networkname": "vnf-net1",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        },
        {
          "broadcasturi": "vlan://1175",
          "deviceid": "9",
          "extradhcpoption": [],
          "gateway": "10.1.1.1",
          "id": "c3473e84-b1d3-4de3-93c2-5144dc48e683",
          "ipaddress": "10.1.1.32",
          "isdefault": false,
          "isolationuri": "vlan://1175",
          "macaddress": "02:01:00:ce:00:08",
          "netmask": "255.255.255.0",
          "networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
          "networkname": "vnf-net2",
          "secondaryip": [],
          "traffictype": "Guest",
          "type": "Isolated"
        }
      ],
      "state": "Running"
    }
  ]
}

Network Mapping Verification:

Device ID Actual Network Expected Network Status
0 vnf-net1 vnf-net1 PASS
1 vnf-net2 vnf-net2 PASS
2 vnf-net3 vnf-net3 PASS
3 test test PASS
4 vnf-net1 vnf-net1 PASS
5 vnf-net2 vnf-net2 PASS
6 vnf-net3 vnf-net3 PASS
7 test test PASS
8 vnf-net1 vnf-net1 PASS
9 vnf-net2 vnf-net2 PASS

Key Finding: The nicnetworklist[X].nic parameter must use the OVA's InstanceID values (6, 9, 10, 11, 12, 13, 14, 15, 16, 17), NOT sequential device IDs (0-9). The UI handles this correctly by reading the InstanceIDs from the template's deployasisdetails. When using the API directly, users must reference the correct InstanceID values from the OVA template.

TC8: Deploy VNF with Missing Required NIC Mapping

Objective: Verify behavior when not all NICs are mapped in the nicnetworklist parameter
Expected Result: Auto-fill
Actual Result: PASSED - Deployment succeeded. Unspecified NICs were auto-filled with the zone's default network (intentional design confirmed via code analysis)
Test Evidence:

(localcloud) 🐱 > deployVnfAppliance templateid=88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd serviceofferingid=63b6851c-631c-4b30-81f0-e959e2eb6052 zoneid=e9594751-da68-4f49-924f-222ba4c15876 name=vnf-tc8-missing-nics properties[0].key=HARole properties[0].value=Standalone nicnetworklist[0].nic=6 nicnetworklist[0].network=4935f651-04b5-49f7-b25a-55c6151ad5cb nicnetworklist[1].nic=9 nicnetworklist[1].network=fee6a3ae-b99f-4ebe-b84b-c661fc4d5888 nicnetworklist[2].nic=10 nicnetworklist[2].network=a170136d-9699-4586-8eaf-f83f19255a54 nicnetworklist[3].nic=11 nicnetworklist[3].network=9427bebb-848d-4b54-8e22-06bfdcc83dcd nicnetworklist[4].nic=12 nicnetworklist[4].network=4935f651-04b5-49f7-b25a-55c6151ad5cb
{
  "virtualmachine": {
    "account": "admin",
    "affinitygroup": [],
    "arch": "x86_64",
    "cpunumber": 1,
    "cpuspeed": 500,
    "created": "2026-01-23T10:44:25+0000",
    "deleteprotection": false,
    "details": {
      "cpuOvercommitRatio": "2.0",
      "dataDiskController": "osdefault",
      "rootDiskController": "lsilogic"
    },
    "displayname": "vnf-tc8-missing-nics",
    "displayvm": true,
    "domain": "ROOT",
    "domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
    "domainpath": "/",
    "guestosid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
    "haenable": false,
    "hasannotations": false,
    "hostcontrolstate": "Enabled",
    "hostid": "cfcf5c46-b2dc-4c40-b487-eb8a111a83b3",
    "hostname": "10.0.35.172",
    "hypervisor": "VMware",
    "id": "a7268a53-e778-43f3-a3a4-b6b3038f0b22",
    "instancename": "i-2-16-VM",
    "ipaddress": "10.1.1.89",
    "isdynamicallyscalable": false,
    "jobid": "f08e5467-0221-4ae7-8331-cdeb8d696e66",
    "jobstatus": 0,
    "lastupdated": "2026-01-23T10:45:02+0000",
    "memory": 512,
    "name": "vnf-tc8-missing-nics",
    "nic": [
      {
        "broadcasturi": "vlan://1179",
        "deviceid": "0",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "b6473fb5-c9d8-4c82-b3db-45922f23e74f",
        "ipaddress": "10.1.1.89",
        "isdefault": true,
        "isolationuri": "vlan://1179",
        "macaddress": "02:01:00:cd:00:08",
        "netmask": "255.255.255.0",
        "networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
        "networkname": "vnf-net1",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "3",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "4b15b3ac-a784-4e04-8f51-650091f4f85e",
        "ipaddress": "10.1.1.199",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:3f",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "7",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "8009e199-db72-4f3b-a33d-c85668a7cd47",
        "ipaddress": "10.1.1.35",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:42",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "9",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "dd193817-d83e-4ea3-8963-cde90b546c2e",
        "ipaddress": "10.1.1.218",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:44",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1164",
        "deviceid": "2",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "45c08e6a-7158-440c-a2b8-ea8298087174",
        "ipaddress": "10.1.1.245",
        "isdefault": false,
        "isolationuri": "vlan://1164",
        "macaddress": "02:01:00:cf:00:08",
        "netmask": "255.255.255.0",
        "networkid": "a170136d-9699-4586-8eaf-f83f19255a54",
        "networkname": "vnf-net3",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "5",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "5569f400-f0d4-485c-ab5f-6189f2fe18b8",
        "ipaddress": "10.1.1.85",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:40",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1179",
        "deviceid": "4",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "39c9d26e-ffdc-4129-953d-adec5482ca7d",
        "ipaddress": "10.1.1.12",
        "isdefault": false,
        "isolationuri": "vlan://1179",
        "macaddress": "02:01:00:cd:00:09",
        "netmask": "255.255.255.0",
        "networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
        "networkname": "vnf-net1",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1175",
        "deviceid": "1",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "dfe7e980-8705-4b2f-a55a-6320883a6d3c",
        "ipaddress": "10.1.1.18",
        "isdefault": false,
        "isolationuri": "vlan://1175",
        "macaddress": "02:01:00:ce:00:09",
        "netmask": "255.255.255.0",
        "networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
        "networkname": "vnf-net2",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "8",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "0d509279-8d6a-44b2-805f-beb50d44e151",
        "ipaddress": "10.1.1.241",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:43",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1161",
        "deviceid": "6",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "da852d6e-551a-48c7-bfd6-e029f7dd4947",
        "ipaddress": "10.1.1.47",
        "isdefault": false,
        "isolationuri": "vlan://1161",
        "macaddress": "02:01:00:cc:00:41",
        "netmask": "255.255.255.0",
        "networkid": "9427bebb-848d-4b54-8e22-06bfdcc83dcd",
        "networkname": "test",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      }
    ],
    "osdisplayname": "Other 2.6x Linux (64-bit)",
    "ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
    "passwordenabled": false,
    "pooltype": "PreSetup",
    "receivedbytes": 0,
    "rootdeviceid": 0,
    "rootdevicetype": "ROOT",
    "securitygroup": [],
    "sentbytes": 0,
    "serviceofferingid": "63b6851c-631c-4b30-81f0-e959e2eb6052",
    "serviceofferingname": "Small Instance",
    "state": "Running",
    "tags": [],
    "templatedisplaytext": "ASAv VNF deploy-as-is test",
    "templateformat": "OVA",
    "templateid": "88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd",
    "templatename": "ASAv-VNF-test-vnf",
    "templatetype": "VNF",
    "userid": "1095c455-f7cd-11f0-bc70-1e00b6000327",
    "username": "admin",
    "zoneid": "e9594751-da68-4f49-924f-222ba4c15876",
    "zonename": "ref-trl-10698-v-Mol8-rositsa-kyuchukova"
  }
}
Device ID Specified? Actual Network
0 Yes (nic=6 → vnf-net1) vnf-net1
1 Yes (nic=9 → vnf-net2) vnf-net2
2 Yes (nic=10 → vnf-net3) vnf-net3
3 Yes (nic=11 → test) test
4 Yes (nic=12 → vnf-net1) vnf-net1
5 No (Not specified) test (auto-filled)
6 No (Not specified) test (auto-filled)
7 No (Not specified) test (auto-filled)
8 No (Not specified) test (auto-filled)
9 No (Not specified) test (auto-filled)

Code Analysis: Auto-fill is intentional, implemented in UserVmManagerImpl.getVmOvfNetworkMapping() - unspecified NICs receive the zone's default network.

TC9: Verify VNF Appliance Functionality Post-Deploy

Objective: Verify deployed VNF appliance is functional
Expected Result: VM runs with correct network configuration matching the deployment specification
Actual Result: PASSED - All 10 NICs correctly mapped to expected networks, VM status Running
Test Evidence:

  • CloudStack UI - VNF Appliances - vnf-tc7-correct-ids - NICs tab showing all 10 NICs with correct network mappings
image image

TC10: Deploy Multiple VNF Appliances from Same Template

Objective: Verify template can be used for multiple deployments
Expected Result: Multiple VMs can be deployed from the same template
**Actual Result: **PASSED - 7 VMs deployed from the same template, 4 Running successfully
Test Evidence:

(localcloud) 🐱 > listVirtualMachines templateid=88ac23d3-a3dd-4bcc-ab69-716a2b6c86dd filter=id,name,state
{
  "count": 7,
  "virtualmachine": [
    {
      "id": "4d319d1f-8de8-4b05-84ba-8b580d731ca5",
      "name": "vnf-tc1-full-api",
      "state": "Running"
    },
    {
      "id": "6d0f73d2-8e3c-474f-9223-2886c15e2cb2",
      "name": "VM-6d0f73d2-8e3c-474f-9223-2886c15e2cb2",
      "state": "Error"
    },
    {
      "id": "46f2bd49-ea2f-4e78-b8df-32510022b955",
      "name": "vnf-ui-test2",
      "state": "Error"
    },
    {
      "id": "a1593da3-fd58-494a-9e4e-977f8f24047c",
      "name": "vnf-ui-test3",
      "state": "Error"
    },
    {
      "id": "92b72388-5fcc-4469-9a28-e24b794b2cd2",
      "name": "vnf-tc7-mixed-networks",
      "state": "Running"
    },
    {
      "id": "3093cba4-9238-44f7-a5d4-198e4df0cad6",
      "name": "vnf-tc7-correct-ids",
      "state": "Running"
    },
    {
      "id": "a7268a53-e778-43f3-a3a4-b6b3038f0b22",
      "name": "vnf-tc8-missing-nics",
      "state": "Running"
    }
  ]
}
Deployment Method Count Status
API (with properties) 4 Running
UI (without properties – bug #12510) 3 Error

Note: The 3 VMs in Error state are due to UI bug #12510 (vApp properties are not sent), not an issue with multiple deployments.

TC11: Regular (non-deploy-as-is) VNF Template Still Works

Objective: Regression test - ensure regular VNF templates still function after PR changes
Expected Result: Existing VNF template functionality unchanged - deployment using networkids parameter works
Actual Result: PASSED - VM deployed successfully with 2 NICs correctly mapped using networkids parameter
Test Evidence:

  • regular VNF template
(localcloud) 🐱 > listVnfTemplates id=117856e5-6d81-40d9-bd77-7b3f1a706435 templatefilter=all filter=id,name,isready,status
{
  "count": 1,
  "template": [
    {
      "id": "117856e5-6d81-40d9-bd77-7b3f1a706435",
      "isready": true,
      "name": "vnf-tc11-regular",
      "status": "Download Complete"
    }
  ]
}
  • appliance deployed successfully with the regular VNF template
(localcloud) 🐱 > deployVnfAppliance templateid=117856e5-6d81-40d9-bd77-7b3f1a706435 serviceofferingid=63b6851c-631c-4b30-81f0-e959e2eb6052 zoneid=e9594751-da68-4f49-924f-222ba4c15876 name=vnf-tc11-regular-deploy networkids=4935f651-04b5-49f7-b25a-55c6151ad5cb,fee6a3ae-b99f-4ebe-b84b-c661fc4d5888
{
  "virtualmachine": {
    "account": "admin",
    "affinitygroup": [],
    "arch": "x86_64",
    "cpunumber": 1,
    "cpuspeed": 500,
    "created": "2026-01-23T12:00:29+0000",
    "deleteprotection": false,
    "details": {
      "cpuOvercommitRatio": "2.0",
      "dataDiskController": "lsilogic",
      "dataDiskControllervmdisk2": "lsilogic",
      "rootDiskController": "ide"
    },
    "displayname": "vnf-tc11-regular-deploy",
    "displayvm": true,
    "domain": "ROOT",
    "domainid": "caacffaf-f7cc-11f0-bc70-1e00b6000327",
    "domainpath": "/",
    "guestosid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
    "haenable": false,
    "hasannotations": false,
    "hostcontrolstate": "Enabled",
    "hostid": "cfcf5c46-b2dc-4c40-b487-eb8a111a83b3",
    "hostname": "10.0.35.172",
    "hypervisor": "VMware",
    "id": "6e78683a-f8d9-4c15-84c8-53fd72f337ed",
    "instancename": "i-2-17-VM",
    "ipaddress": "10.1.1.31",
    "isdynamicallyscalable": false,
    "isodisplaytext": "day0.iso",
    "isoid": "222b267d-0b28-4ce5-976d-6dfa6493aed5",
    "isoname": "day0.iso",
    "jobid": "9040d257-ea37-4cd1-9d2b-3866c898cec5",
    "jobstatus": 0,
    "lastupdated": "2026-01-23T12:01:07+0000",
    "memory": 512,
    "name": "vnf-tc11-regular-deploy",
    "nic": [
      {
        "broadcasturi": "vlan://1175",
        "deviceid": "1",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "0ca0727f-e737-4ee2-9343-41837b2445b3",
        "ipaddress": "10.1.1.254",
        "isdefault": false,
        "isolationuri": "vlan://1175",
        "macaddress": "02:01:00:ce:00:0a",
        "netmask": "255.255.255.0",
        "networkid": "fee6a3ae-b99f-4ebe-b84b-c661fc4d5888",
        "networkname": "vnf-net2",
        "publicip": "10.0.52.188",
        "publicipid": "0ac05a28-6a86-476a-ae41-53e1162f9396",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      },
      {
        "broadcasturi": "vlan://1179",
        "deviceid": "0",
        "extradhcpoption": [],
        "gateway": "10.1.1.1",
        "id": "230e3d30-409e-40ce-81d1-31043d2ec66b",
        "ipaddress": "10.1.1.31",
        "isdefault": true,
        "isolationuri": "vlan://1179",
        "macaddress": "02:01:00:cd:00:0a",
        "netmask": "255.255.255.0",
        "networkid": "4935f651-04b5-49f7-b25a-55c6151ad5cb",
        "networkname": "vnf-net1",
        "publicip": "10.0.52.187",
        "publicipid": "5f84bd0b-8c78-4cbe-96f4-16ed55320408",
        "secondaryip": [],
        "traffictype": "Guest",
        "type": "Isolated"
      }
    ],
    "osdisplayname": "Other 2.6x Linux (64-bit)",
    "ostypeid": "cac8e8aa-f7cc-11f0-bc70-1e00b6000327",
    "passwordenabled": false,
    "pooltype": "PreSetup",
    "publicip": "10.0.52.187",
    "publicipid": "5f84bd0b-8c78-4cbe-96f4-16ed55320408",
    "receivedbytes": 0,
    "rootdeviceid": 0,
    "rootdevicetype": "ROOT",
    "securitygroup": [],
    "sentbytes": 0,
    "serviceofferingid": "63b6851c-631c-4b30-81f0-e959e2eb6052",
    "serviceofferingname": "Small Instance",
    "state": "Running",
    "tags": [],
    "templatedisplaytext": "TC11 Regular VNF template",
    "templateformat": "OVA",
    "templateid": "117856e5-6d81-40d9-bd77-7b3f1a706435",
    "templatename": "vnf-tc11-regular",
    "templatetype": "VNF",
    "userid": "1095c455-f7cd-11f0-bc70-1e00b6000327",
    "username": "admin",
    "vnfnics": [
      {
        "deviceid": 0,
        "management": true,
        "name": "management",
        "required": true
      },
      {
        "deviceid": 1,
        "management": true,
        "name": "wan",
        "required": true
      }
    ],
    "zoneid": "e9594751-da68-4f49-924f-222ba4c15876",
    "zonename": "ref-trl-10698-v-Mol8-rositsa-kyuchukova"
  }
}
Device ID VNF NIC Name (from template) Network We Specified Network VM Actually Got
0 management vnf-net1 (1st in list) vnf-net1
1 wan vnf-net2 (2nd in list) vnf-net2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants